home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / bench / server.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-16  |  14.9 KB  |  551 lines

  1. /* 
  2.  * server.c --
  3.  *
  4.  *    The server part of some multi-program synchronization primatives.
  5.  *    The routines here control N client programs.  This just means
  6.  *    telling them all to start, and hearing back from them when they're done.
  7.  *
  8.  * Copyright 1986 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #ifndef lint
  13. static char rcsid[] = "$Header: /sprite/src/cmds/bench/RCS/server.c,v 1.12 90/02/16 11:10:41 jhh Exp $ SPRITE (Berkeley)";
  14. #endif not lint
  15.  
  16.  
  17. #include "sprite.h"
  18. #include "status.h"
  19. #include "fs.h"
  20. #include "dev/pdev.h"
  21. #include "sys/file.h"
  22. #include "stdio.h"
  23. #include "bit.h"
  24. #include "sys.h"
  25.  
  26. char *pdev="/sprite/daemons/bench.pdev";
  27.  
  28. typedef int  (*IntProc)();
  29.  
  30. typedef struct ServerState {
  31.     int cntlStream;        /* StreamID of pdev control stream */
  32.     int numClients;        /* Number of client processes */
  33.     int *clientStream;        /* Array of server streamIDs used to communicate
  34.                  * with the N clients */
  35.     int maxStreamID;        /* Largest value in clientStream array */
  36.     char *clientState;        /* Array of state words, one per client */
  37.     Address *requestBuf;    /* Array of pointers to request buffers.  The
  38.                  * kernel puts request directly into these. */
  39.     int *selectMask;        /* Mask used to wait for requests */
  40.     int selectMaskBytes;    /* Number of bytes in selectMask */
  41.     IntProc opTable[7];        /* Op. switch for servicing requests */
  42. } ServerState;
  43.  
  44. /*
  45.  * Flags for the client state words.
  46.  */
  47. #define CLIENT_OPENED    0x1
  48. #define CLIENT_STARTED    0x2
  49. #define CLIENT_FINISHED    0x4
  50.  
  51. /*
  52.  * The size of the request buffers.
  53.  */
  54. #define REQ_BUF_SIZE    128
  55.  
  56. extern int errno;
  57.  
  58. /*
  59.  * Forward Declarations
  60.  */
  61. ReturnStatus ServeOpen();
  62. ReturnStatus ServeRead();
  63. ReturnStatus ServeWrite();
  64. ReturnStatus ServeIOControl();
  65. ReturnStatus ServeClose();
  66.  
  67. Pdev_Op ServeRequest();
  68.  
  69.  
  70. /*
  71.  *----------------------------------------------------------------------
  72.  *
  73.  * ServerSetup --
  74.  *
  75.  *    Establish contact with N clients.  A pseudo device is opened
  76.  *    and we are declared its "master", or "server".  After this
  77.  *    other processes can open the pseudo device and we'll get a private
  78.  *    stream back that we use for requests from that process.
  79.  *
  80.  * Results:
  81.  *    A pointer to state about the clients needed by ServerStart and
  82.  *    ServerWait.
  83.  *
  84.  * Side effects:
  85.  *    Opens the pseudo device as the server and waits for numClients
  86.  *    opens by client processes.
  87.  *    This exits (kills the process) upon error.
  88.  *
  89.  *----------------------------------------------------------------------
  90.  */
  91.  
  92. void
  93. ServerSetup(numClients, dataPtr)
  94.     int numClients;
  95.     ClientData *dataPtr;
  96. {
  97.     ServerState *statePtr;
  98.     int client;
  99.     int len;
  100.     int amountRead;
  101.     ReturnStatus status;
  102.     Pdev_Notify notify;
  103.     int streamID;
  104.     Pdev_SetBufArgs setBuf;
  105.     extern Boolean waitForSignal;
  106.     extern Boolean startClients;
  107.  
  108.     statePtr = (ServerState *)malloc(sizeof(ServerState));
  109.     statePtr->clientStream = (int *)malloc(numClients * sizeof(int));
  110.     statePtr->clientState = (char *)malloc(numClients);
  111.     statePtr->requestBuf = (Address *)malloc(numClients * sizeof(Address));
  112.     statePtr->numClients = numClients;
  113.  
  114.     statePtr->opTable[(int)PDEV_OPEN] = ServeOpen;
  115.     statePtr->opTable[(int)PDEV_CLOSE] = ServeClose;
  116.     statePtr->opTable[(int)PDEV_READ] = ServeRead;
  117.     statePtr->opTable[(int)PDEV_WRITE] = ServeWrite;
  118.     statePtr->opTable[(int)PDEV_IOCTL] = ServeIOControl;
  119.  
  120.     /*
  121.      * Open the pseudo device.
  122.      */
  123.     statePtr->cntlStream = open(pdev, O_RDONLY|O_MASTER, 0666);
  124.     if (statePtr->cntlStream < 0) {
  125.     statePtr->cntlStream = open(pdev, O_CREAT|O_RDONLY|O_MASTER, 0666);
  126.     }
  127.     if (statePtr->cntlStream < 0) {
  128.     Stat_PrintMsg(errno, "Error opening pseudo device as master");
  129.     exit(errno);
  130.     }
  131.     for (client=0 ; client<numClients ; client++) {
  132.     /*
  133.      * Read on our control stream (the one we just opened) messages
  134.      * that contain new streamIDs.  These are for private streams
  135.      * back to the client process.
  136.      */
  137.     len = sizeof(notify);
  138.     amountRead = read(statePtr->cntlStream, (Address)¬ify, len);
  139.     if (amountRead < 0) {
  140.         Stat_PrintMsg(errno, "Error reading control stream");
  141.         exit(errno);
  142.     } else if (amountRead != sizeof(notify)) {
  143.         fprintf(stderr,
  144.         "Warning, short read (%d) on control stream\n", amountRead);
  145.         fflush(stderr);
  146.     }
  147.     streamID = notify.newStreamID;
  148.     if (streamID > statePtr->maxStreamID) {
  149.         statePtr->maxStreamID = streamID;
  150.     }
  151.     /*
  152.      * Set up state for the client.
  153.      */
  154.     statePtr->clientStream[client] = streamID;
  155.     statePtr->clientState[client] = CLIENT_OPENED;
  156.     statePtr->requestBuf[client] = (Address) malloc(REQ_BUF_SIZE);
  157.     /*
  158.      * Tell the kernel where the request buffer is.
  159.      */
  160.     setBuf.requestBufAddr = statePtr->requestBuf[client];
  161.     setBuf.requestBufSize = REQ_BUF_SIZE;
  162.     setBuf.readBufAddr = NULL;
  163.     setBuf.readBufSize = 0;
  164.     Fs_IOControl(streamID, IOC_PDEV_SET_BUF, sizeof(Pdev_SetBufArgs),
  165.             (Address)&setBuf, 0, (Address)NULL);
  166.  
  167.     fprintf(stderr, "Got client on stream %d\n",streamID);
  168.     fflush(stderr);
  169.     }
  170.     if (waitForSignal) {
  171.     while (!startClients) {
  172.         sigpause(0);
  173.     }
  174.     }
  175.     /*
  176.      * Now start all clients at once by servicing their first PDEV_OPEN
  177.      * request.
  178.      */
  179.     for (client=0 ; client<numClients ; client++) {
  180.     (void) ServeRequest(statePtr->clientStream[client],
  181.              statePtr->requestBuf[client], statePtr->opTable);
  182.     }
  183.     fflush(stderr);
  184.     /*
  185.      * Now that we know the largest stream ID used for a client stream
  186.      * we can allocate and initialize the select mask for the streams.
  187.      */
  188.     statePtr->selectMaskBytes = Bit_NumBytes(statePtr->maxStreamID);
  189.     statePtr->selectMask = (int *)malloc(statePtr->selectMaskBytes);
  190.     bzero((Address)statePtr->selectMask, statePtr->selectMaskBytes);
  191.     for (client=0 ; client < numClients ; client++) {
  192.     Bit_Set(statePtr->clientStream[client], statePtr->selectMask);
  193.     }
  194.     *dataPtr = (ClientData)statePtr;
  195. }
  196.  
  197. /*
  198.  *----------------------------------------------------------------------
  199.  *
  200.  * ServeRequest --
  201.  *
  202.  *    The top level service routine that reads client requests
  203.  *    and branches out to a handler for the request.  This takes
  204.  *    care of error conditions and allocating space for the
  205.  *    request and the reply parameters.
  206.  *
  207.  * Results:
  208.  *    None
  209.  *
  210.  * Side effects:
  211.  *    Reads and writes on the client's stream.  malloc space for the
  212.  *    request and the reply.  Will reset the client stream upon error.
  213.  *
  214.  *----------------------------------------------------------------------
  215.  */
  216.  
  217. Pdev_Op
  218. ServeRequest(clientStreamID, requestBuf, opTable)
  219.     int clientStreamID;        /* StreamID of private channel to client */
  220.     Address requestBuf;        /* Buffer that holds client's requests */
  221.     IntProc *opTable;        /* Operation switch table */
  222. {
  223.     int amountRead;
  224.     ReturnStatus status;
  225.     Pdev_BufPtrs bufPtrs;        /* Used to read ptrs into req. buf. */
  226.     Pdev_Request *requestPtr;    /* Points to request header */
  227.     Pdev_Reply reply;
  228.     Address requestData;        /* Points to data that follows header */
  229.     char replyBuf[1024];
  230.     char *replyData = replyBuf;        /* Points to reply data */
  231.     int replySize;            /* Amount of valid data in replyBuf */
  232.     Boolean alloc;
  233.  
  234.     /*
  235.      * Read the request header that indicates the operation and the
  236.      * offset within the request buffer of the request message.
  237.      */
  238.     amountRead = read(clientStreamID, (Address)&bufPtrs, sizeof(Pdev_BufPtrs));
  239.     if (amountRead < 0) { 
  240.     Stat_PrintMsg(errno, "ServeRequest: error reading request bufPtrs");
  241.     goto failure;
  242.     } else if (amountRead != sizeof(Pdev_BufPtrs)) {
  243.     fprintf(stderr,
  244.         "ServeRequest: short read (%d) of request bufPtrs\n", amountRead);
  245.     fflush(stderr);
  246.     goto failure;
  247.     } else if ((int)bufPtrs.magic != PDEV_BUF_PTR_MAGIC) {
  248.     fprintf(stderr, "ServeRequest: bad bufPtr magic 0x%x\n",
  249.         bufPtrs.magic);
  250.     status = FAILURE;
  251.     goto failure;
  252.     }
  253.     /*
  254.      * While there are still requests in the buffer, service them.
  255.      */
  256.     while (bufPtrs.requestFirstByte < bufPtrs.requestLastByte) {
  257.     requestPtr = (Pdev_Request *)&requestBuf[bufPtrs.requestFirstByte];
  258.     if (requestPtr->hdr.magic != PDEV_REQUEST_MAGIC) {
  259.         /*
  260.         Sys_Panic(SYS_FATAL, "ServeRequest, bad request magic # 0x%x\n",
  261.                 requestPtr->magic);
  262.         */
  263.         abort();
  264.     }
  265.     /*
  266.      * Set up a buffer for the reply data;
  267.      */
  268.     if (requestPtr->hdr.replySize > 1024) {
  269.         alloc = TRUE;
  270.         replyData = (Address) malloc(requestPtr->hdr.replySize);
  271.     } else {
  272.         alloc = FALSE;
  273.         replyData = replyBuf;
  274.     }
  275.     requestData = (Address)((int)requestPtr + sizeof(Pdev_Request));
  276.     /*
  277.      * Switch out the to the handler for the pdev operation.
  278.      */
  279.     status = (*opTable[(int)requestPtr->hdr.operation])(clientStreamID,
  280.             requestPtr, requestData, replyData, &replySize);
  281.     /*
  282.      * Copy the data into the reply and give it to the kernel.
  283.      */
  284.     
  285.     reply.magic = PDEV_REPLY_MAGIC;
  286.     reply.status = status;
  287.     reply.selectBits = FS_READ|FS_WRITE;
  288.     reply.replySize = replySize;
  289.     reply.replyBuf = replyData;
  290.     reply.signal = 0;
  291.     reply.code = 0;
  292.     status = Fs_IOControl(clientStreamID, IOC_PDEV_REPLY,
  293.                 sizeof(Pdev_Reply), (Address) &reply, 0,
  294.                 (Address) NULL);
  295.     if (status != SUCCESS) {
  296.         /*
  297.         Sys_Panic(SYS_FATAL, "%s; status \"%s\"",
  298.             "ServeRequest couldn't send reply",
  299.             Stat_GetMsg(status));
  300.         */
  301.         abort();
  302.     }
  303.     if (alloc) {
  304.         free(replyData);
  305.     }
  306.     /*
  307.      * Tell the kernel we removed a request and see if there are any more.
  308.      */
  309.     bufPtrs.requestFirstByte += requestPtr->hdr.messageSize;
  310.     Fs_IOControl(clientStreamID, IOC_PDEV_SET_PTRS,
  311.             sizeof(Pdev_BufPtrs), (Address)&bufPtrs, 0, (Address) NULL);
  312.     }
  313.     return(requestPtr->hdr.operation);
  314.  
  315. failure:
  316.     /*
  317.      * Couldn't even get started right.  We'd like to be able to "reset
  318.      * the connection" at this point - do something to cause the waiting
  319.      * client to return, and something to flush any remaining input
  320.      * in the request stream.  Need a special IOControl.
  321.      */
  322.     close(clientStreamID);
  323.     return((Pdev_Op)-1);
  324. }
  325.  
  326. /*
  327.  *----------------------------------------------------------------------
  328.  *
  329.  * Serve --
  330.  *
  331.  *    Listen for requests from client's, returning after all clients
  332.  *    have closed their streams.
  333.  *
  334.  * Results:
  335.  *    None
  336.  *
  337.  * Side effects:
  338.  *    Handle all requests by clients.
  339.  *
  340.  *----------------------------------------------------------------------
  341.  */
  342.  
  343. void
  344. Serve(data)
  345.     ClientData data;
  346. {
  347.     ServerState *statePtr;
  348.     int client;
  349.     ReturnStatus status;
  350.     int *selectMask;
  351.     int numFinishedClients;
  352.     int numReady;
  353.     int numBits;
  354.  
  355.     statePtr = (ServerState *)data;
  356.     selectMask = (int *)malloc(statePtr->selectMaskBytes);
  357.     numBits = statePtr->selectMaskBytes * BIT_NUM_BITS_PER_BYTE;
  358.     numFinishedClients = 0;
  359.     do {
  360.     bcopy( (Address)statePtr->selectMask, (Address)selectMask, 
  361.         statePtr->selectMaskBytes);
  362.     status = Fs_Select(numBits, (Time *)NULL, selectMask,
  363.                 (int *)NULL, (int *)NULL, &numReady);
  364.     if (status != SUCCESS) {
  365.         /*
  366.         Sys_Panic(SYS_FATAL, "Serve: select failed, %s\n",
  367.         Stat_GetMsg(status));
  368.        */
  369.        abort();
  370.     }
  371.     for (client=0 ; client < statePtr->numClients ; client++) {
  372.         /*
  373.          * Look for the each client's bit in the select mask and
  374.          * service requests that have arrived.
  375.          */
  376.         if (Bit_IsSet(statePtr->clientStream[client], selectMask)) {
  377.         /*
  378.          * Handle the client's request.  If it's a close
  379.          * then clear the client's bit from the select mask so
  380.          * don't bother checking it again.
  381.          */
  382.         if (ServeRequest(statePtr->clientStream[client],
  383.                  statePtr->requestBuf[client],
  384.                  statePtr->opTable) == PDEV_CLOSE) {
  385.             fprintf(stderr, "Client %d closed... ", client);
  386.             fflush(stderr);
  387.             numFinishedClients++;
  388.             statePtr->clientState[client] |= CLIENT_FINISHED;
  389.             Bit_Clear(statePtr->clientStream[client],
  390.                 statePtr->selectMask);
  391.         }
  392.         }
  393.     }
  394.     } while (numFinishedClients < statePtr->numClients);
  395.     fprintf(stderr, "\n");
  396.     fflush(stderr);
  397. }
  398.  
  399. /*
  400.  *----------------------------------------------------------------------
  401.  *
  402.  * ServeOpen --
  403.  *
  404.  *    React to an Open or Dup request.
  405.  *
  406.  * Results:
  407.  *    SUCCESS
  408.  *
  409.  * Side effects:
  410.  *    Print statement.
  411.  *
  412.  *----------------------------------------------------------------------
  413.  */
  414. /*ARGSUSED*/
  415. ReturnStatus
  416. ServeOpen(streamID, requestPtr, requestData, replyData, replySizePtr)
  417.     int streamID;
  418.     Pdev_Request *requestPtr;
  419.     Address requestData;
  420.     Address replyData;
  421.     int *replySizePtr;
  422. {
  423.     fprintf(stderr, "Open request, streamID %d, pid %x\n",
  424.         streamID, requestPtr->param.open.pid);
  425.     fflush(stderr);
  426.     *replySizePtr = 0;
  427.     return(SUCCESS);
  428. }
  429.  
  430. /*
  431.  *----------------------------------------------------------------------
  432.  *
  433.  * ServeRead --
  434.  *
  435.  *    Return data for a read request.
  436.  *
  437.  * Results:
  438.  *    SUCCESS
  439.  *
  440.  * Side effects:
  441.  *    Zeroes out the reply buffer.
  442.  *
  443.  *----------------------------------------------------------------------
  444.  */
  445. /*ARGSUSED*/
  446. ReturnStatus
  447. ServeRead(streamID, requestPtr, requestBuf, replyBuf, replySizePtr)
  448.     int streamID;
  449.     Pdev_Request *requestPtr;
  450.     Address requestBuf;
  451.     Address replyBuf;
  452.     int *replySizePtr;
  453. {
  454.     if (requestPtr->hdr.replySize > 0) {
  455.     bzero(replyBuf, requestPtr->hdr.replySize);
  456.     }
  457.     *replySizePtr = requestPtr->hdr.replySize;
  458.     return(SUCCESS);
  459. }
  460.  
  461. /*
  462.  *----------------------------------------------------------------------
  463.  *
  464.  * ServeWrite --
  465.  *
  466.  *    Handle a write request.
  467.  *
  468.  * Results:
  469.  *    SUCCESS
  470.  *
  471.  * Side effects:
  472.  *    Sets up the return value, the number of bytes written.
  473.  *
  474.  *----------------------------------------------------------------------
  475.  */
  476. /*ARGSUSED*/
  477. ReturnStatus
  478. ServeWrite(streamID, requestPtr, requestBuf, replyBuf, replySizePtr)
  479.     int streamID;
  480.     Pdev_Request *requestPtr;
  481.     Address requestBuf;
  482.     Address replyBuf;
  483.     int *replySizePtr;
  484. {
  485.     *replySizePtr = 0;
  486.     return(SUCCESS);
  487. }
  488.  
  489. /*
  490.  *----------------------------------------------------------------------
  491.  *
  492.  * ServeIOControl --
  493.  *
  494.  *    Handle an IOControl.  This acts like an echo now.
  495.  *
  496.  * Results:
  497.  *    SUCCESS
  498.  *
  499.  * Side effects:
  500.  *    Copies the request buffer to the reply buffer.
  501.  *
  502.  *----------------------------------------------------------------------
  503.  */
  504. /*ARGSUSED*/
  505. ReturnStatus
  506. ServeIOControl(streamID, requestPtr, requestBuf, replyBuf, replySizePtr)
  507.     int streamID;
  508.     Pdev_Request *requestPtr;
  509.     Address requestBuf;
  510.     Address replyBuf;
  511.     int *replySizePtr;
  512. {
  513.     if (requestPtr->hdr.replySize <= requestPtr->hdr.requestSize) {
  514.     bcopy(requestBuf, replyBuf, requestPtr->hdr.replySize);
  515.     } else {
  516.     bcopy(requestBuf, replyBuf, requestPtr->hdr.requestSize);
  517.     bzero( replyBuf[requestPtr->hdr.requestSize],
  518.         requestPtr->hdr.replySize - requestPtr->hdr.requestSize);
  519.     }
  520.     *replySizePtr = requestPtr->hdr.replySize;
  521.     return(SUCCESS);
  522. }
  523.  
  524. /*
  525.  *----------------------------------------------------------------------
  526.  *
  527.  * ServeClose --
  528.  *
  529.  *    Handle a close request.
  530.  *
  531.  * Results:
  532.  *    SUCCESS
  533.  *
  534.  * Side effects:
  535.  *    None.
  536.  *
  537.  *----------------------------------------------------------------------
  538.  */
  539. /*ARGSUSED*/
  540. ReturnStatus
  541. ServeClose(streamID, requestPtr, requestBuf, replyBuf, replySizePtr)
  542.     int streamID;
  543.     Pdev_Request *requestPtr;
  544.     Address requestBuf;
  545.     Address replyBuf;
  546.     int *replySizePtr;
  547. {
  548.     *replySizePtr = 0;
  549.     return(SUCCESS);
  550. }
  551.